using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace GameStateManagement
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Ship : Actor
    {
        public static float ForwardThrust = 40000f;
        public static float BackwardThrust = 5000f;
        public static float StabilizationConst = (1f/20f);
        public static float DecelerationConst = 24f;
        public static float ShipRotSpeed = 150.0f;
        public static float MissileForce = 600.0f;
        public static float MissileCooldownTime = 1000.0f;
        public bool isInvincible = false;
        public bool isBoosted = false;
        public Vector3 previousColor;

        int m_LastMissileFireTime = -(int)MissileCooldownTime; // Initial value that won't restrict for the first moments of the game starting.

        public List<Missile> missiles = new List<Missile>();

        public Vector3 shipControlForce = Vector3.Zero;
        public Force shipDecelerationForce;

        public Ship(Game game)
            : base(game)
        {
            sMeshName = "SpaceShip";

            // Physics
            fMass = 100.0f;
            fTerminalVelocity = 1500.0f;
            vAcceleration = Vector3.Zero;
            bPhysicsDriven = true;

            // Apply pi/2 rotation on X axis.
            m_qRotation = Quaternion.CreateFromAxisAngle(Vector3.UnitX, MathHelper.PiOver2);
            m_qRotation *= Quaternion.CreateFromAxisAngle(Vector3.UnitY, MathHelper.PiOver2);
            m_vWorldPosition = new Vector3(0, 4500f, 0);
            shipDecelerationForce = CreateForce("Ship Decel Force");

            use_effect = false;
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            //GameplayScreen.soundbank.PlayCue("Ship_Spawn");

            // Tell camera to follow me.
            GameplayScreen.FollowCamera.SetSubject(this);

            // Tell WormholeManager some information.
            WormholeManager.GetWormholeManager().SetShip(this);
            WormholeManager.GetWormholeManager().AddToScope(this, 5f, 1000f);

            base.Initialize();
        }

        protected override void LoadContent()
        {
            load_matrices(GameplayScreen.FollowCamera.m_CameraMatrix, Matrix.CreateTranslation(WorldTransform.Translation), GameplayScreen.FollowCamera.m_ProjectionMatrix, Game.Content); 

            base.LoadContent();
        }

        public override void Update(GameTime gameTime)
        {
            for (int i = missiles.Count - 1; i >= 0; i--)
            {
                if (System.Environment.TickCount - missiles[i].spawnTime >= Missile.m_MissileLifeTime)
                {
                    Game.Components.Remove(missiles[i]);
                    missiles.Remove(missiles[i]);
                }
            }
            base.Update(gameTime);
        }

        /// <summary>
        /// Modified ship physics to give better control.
        /// </summary>
        protected override void DrivePhysics()
        {
            if (shipControlForce != Vector3.Zero && m_vVelocity != Vector3.Zero)
            {
                Vector3 dir = shipControlForce;
                dir.Normalize();
                float magnitude = m_vVelocity.Length();
                m_vVelocity += Ship.StabilizationConst * magnitude * dir;
            }

            m_vVelocity += vAcceleration * GameplayScreen.fDelta / 2.0f;
            m_vWorldPosition += m_vVelocity * GameplayScreen.fDelta;
            vAcceleration = (shipControlForce + vForce) / fMass;
            m_vVelocity += vAcceleration * GameplayScreen.fDelta / 2.0f;

            // Terminal velocity check
            if (m_vVelocity.LengthSquared() > Math.Pow(fTerminalVelocity, 2.0f))
            {
                m_vVelocity.Normalize();
                m_vVelocity *= fTerminalVelocity;
            }
        }

        public void Reset()
        {
            // Initial ship state
            vAcceleration = Vector3.Zero;
            m_vVelocity = Vector3.Zero;
            m_vWorldPosition = Vector3.Zero;
            m_qRotation = Quaternion.CreateFromAxisAngle(Vector3.UnitX, MathHelper.PiOver2);
        }

        public void FireMissile()
        {
            if (System.Environment.TickCount - m_LastMissileFireTime >= MissileCooldownTime)
            {
                // Create missile
                Missile missile = new Missile(Game);
                missile.Enemy_Missile = false;
                Game.Components.Add(missile);
                missiles.Add(missile);

                // Position the missile, angle, and velocity.
                missile.m_vWorldPosition = this.m_vWorldPosition;
                missile.m_qRotation = this.m_qRotation;
                missile.moving_vector =  WorldTransform.Forward;
                missile.Speed = 5000;
                m_LastMissileFireTime = System.Environment.TickCount;

                // Play sound
                GameplayScreen.soundbank.PlayCue("Ship_Missile");
            }
        }

        public void activateShield()
        {
            previousColor = m_DiffuseColor;
            m_DiffuseColor = Color.Purple.ToVector3();
        }
        public void deactivateShield()
        {
            m_DiffuseColor = previousColor;
            isInvincible = false;
        }
        public void activateSpeed()
        {
            previousColor = m_DiffuseColor;
            m_DiffuseColor = Color.Orange.ToVector3();
        }
        public void deactivateSpeed()
        {
            m_DiffuseColor = previousColor;
            isBoosted = false;
            m_vVelocity /= 2;
            fTerminalVelocity /= 2;
        }
    }
}
